/********************************************
 * 功能说明: 
 * 模块名称: 
 * 系统名称: 
 * 软件版权: 北京银杉金服科技有限公司
 * 系统版本: 1.0.0
 * 开发人员: zhangfb
 * 开发时间: 2019/1/13 18:26
 * 审核人员: 
 * 相关文档: 
 * 修改记录: 修改日期 修改人员 修改说明
 *********************************************/
package com.hyacinth.server.init;

import com.hyacinth.server.AuroraServer;
import com.hyacinth.server.bean.AuroraBeanManager;
import com.hyacinth.server.config.AbstractConfiguration;
import com.hyacinth.server.config.AppConfig;
import com.hyacinth.server.config.ApplicationConfiguration;
import com.hyacinth.server.config.ConfigurationHolder;
import com.hyacinth.server.constant.Constant;
import com.hyacinth.server.enums.ServerChannel;
import com.hyacinth.server.enums.StatusEnum;
import com.hyacinth.server.exception.AuroraException;
import com.hyacinth.server.thread.ThreadLocalHolder;
import com.hyacinth.server.util.ClassScanner;
import com.hyacinth.server.util.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.List;
import java.util.Properties;

import static com.hyacinth.server.constant.Constant.SystemProperties.*;

/**
 * 初始化过程
 * @author zhangfb
 * @version 1.0.0.1
 * @since JDK 1.8
 */
public class AuroraInitialization {

    private static final Logger LOGGER = LoggerFactory.getLogger(AuroraInitialization.class);

    /**
     * 初始化操作
     * @param clazz 启动类
     * @param serverContextPath 上下文根路径
     * @param port 端口
     */
    public static void doInit(Class<?> clazz, String serverContextPath, Integer port) throws Exception {
        // 打印logo
        logo();

        // 初始化配置
        initConfiguration(clazz);

        // 设置应用配置
        setAppConfig(clazz, serverContextPath, port);

        // 初始化bean工厂
        AuroraBeanManager.getInstance().init();

    }

    /**
     * 1、打印logo
     * 2、设置当前线程名
     */
    private static void logo() {
        System.out.println(LOGO);
        Thread.currentThread().setName(APPLICATION_THREAD_MAIN_NAME);
    }

    /**
     * 初始化配置
      * @param clazz 启动类
     */
    private static void initConfiguration(Class<?> clazz) throws Exception {
        if (clazz.getPackage() == null) {
            throw new AuroraException(StatusEnum.NULL_PACKAGE, "[" + clazz.getName() + ".java]");
        }
        // 设置当前应用初始化时间
        ThreadLocalHolder.setLocalTime(System.currentTimeMillis());
        // 加载所有的配置类
        List<Class<?>> configuration = ClassScanner.getConfiguration(clazz.getPackage().getName());
        for (Class<?> aClass : configuration) {
            AbstractConfiguration conf = (AbstractConfiguration) aClass.newInstance();
            // 获取配置文件名称
            String propertiesName = conf.getPropertiesName();
            if (StringUtils.isBlank(propertiesName)) {
                LOGGER.warn("配置类未设置配置文件名称，Configuration Class: {}", aClass.getName());
                continue;
            }

            InputStream stream;
            // 重启动参数中获取配置文件名称
            String sysProperty = System.getProperty(propertiesName);
            if (sysProperty != null) {
                stream = new FileInputStream(new File(sysProperty));
            } else {
                // 使用启动类的加载器加载属性文件流
                stream = AuroraServer.class.getClassLoader().getResourceAsStream(propertiesName);
            }

            Properties properties = new Properties();
            properties.load(stream);
            conf.setProperties(properties);

            // 配置文件全局缓存
            ConfigurationHolder.addConfiguration(aClass.getName(), conf);
        }
    }

    /**
     * 设置应用配置
     * @param clazz 启动类
     * @param serverContextPath 上下文根路径
     * @param port 端口
     */
    private static void setAppConfig(Class<?> clazz, String serverContextPath, Integer port) {
        // 获取应用配置
        ApplicationConfiguration appConf = (ApplicationConfiguration) ConfigurationHolder.getConfiguration(ApplicationConfiguration.class);
        if (serverContextPath == null) {
            serverContextPath = appConf.get(Constant.SERVER_CONTEXT_PATH);
        }
        if (port == null) {
            try {
                port = Integer.parseInt(appConf.get(Constant.SERVER_PORT));
            } catch (Exception e) {
                throw new AuroraException(StatusEnum.PORT_CONF_ERROR, "[" + appConf.get(Constant.SERVER_PORT) + "]");
            }
        }

        if (serverContextPath == null) {
            throw new AuroraException("No [server.context.path] exists");
        }

        // 如果未配置，默认是Netty
        ServerChannel serverChannel = ServerChannel.Netty;
        String serverChannelName = appConf.get(Constant.SERVER_CHANNEL);
        if (serverChannelName != null) {
            serverChannel = ServerChannel.getByName(serverChannelName);
        }

        // 设置应用配置类
        AppConfig appConfig = AppConfig.getInstance();
        appConfig.setPort(port);
        appConfig.setServerChannel(serverChannel);
        appConfig.setServerContextPath(serverContextPath);
        appConfig.setRootPackageName(clazz.getPackage().getName());
    }


}
